package com.jishuo.nontax.bfc.service;

import com.github.pagehelper.PageHelper;
import com.jishuo.base.bean.BaseResult;
import com.jishuo.base.bean.ErrorCodeEnum;
import com.jishuo.base.bean.Pagination;
import com.jishuo.base.config.NonTaxConfig;
import com.jishuo.base.service.SequenceService;
import com.jishuo.base.util.CommonUtil;
import com.jishuo.base.util.ExportSXSSFUtil;
import com.jishuo.base.util.StringUtil;
import com.jishuo.nontax.bean.bank.OnlineOrder;
import com.jishuo.nontax.bean.bank.PayFisc;
import com.jishuo.nontax.bean.message.SetBankPayFiscBackOut;
import com.jishuo.nontax.bean.message.SetPayFisc;
import com.jishuo.nontax.bean.message.SetPayFiscNew;
import com.jishuo.nontax.bean.vo.PayFiscVO;
import com.jishuo.nontax.bfc.dao.FiscMapper;
import com.jishuo.nontax.bfc.pzk.PzkService;
import com.jishuo.nontax.bfc.tlq.MessageFactory;
import com.jishuo.nontax.bfc.tlq.MessageService;
import com.jishuo.nontax.util.BillStateUtil;
import com.jishuo.nontax.util.PzkUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author :hanlipeng
 * @description :
 * @create :2022-12-22 09:38:00
 */
@Service
public class FiscService {
    private static Logger logger = LoggerFactory.getLogger(FiscService.class);

    @Resource
    private FiscMapper fiscMapper;
    @Resource
    private SequenceService sequenceService;
    @Resource
    private MessageService messageService;
    @Resource
    private NonTaxConfig nonTaxConfig;
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Resource
    private OnlineOrderService onlineOrderService;
    @Resource
    private PzkService  pzkService;
    @Resource
    private PzkUtils pzkUtils;

    /**
     * 划解国库缴费信息
     *
     * @param billnum     票号
     * @param bankaffirm  交易流水号
     * @param paybankdt   交易时间
     * @param bankstation 网点
     * @return
     */
    public BaseResult setFiscPayInfo(String billnum, String bankaffirm, String paybankdt, String bankstation, String paychnl) {
        // 参数检查
        String retMsg = "";
        if (billnum == null || "".equals(billnum)) {
            retMsg += "票号未填写；";
        } else if (paybankdt == null || "".equals(paybankdt)) {
            retMsg += "缴费时间未填写；";
        } else if (bankaffirm == null || "".equals(bankaffirm)) {
            retMsg += "交易流水号未填写；";
        }
        if (!"".equals(retMsg)) {
            logger.info("缴费参数错误。" + retMsg);
            return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        }

        PayFiscVO fiscInfo = fiscMapper.findFiscInfo(billnum);
        //判断单据信息是否存在
        if (fiscInfo == null) {
            logger.info("单据缴款号不存在（票号：" + billnum + "）");
            return new BaseResult(ErrorCodeEnum.BILL_NOT_FOUND);
        }
        // 判断是否已缴费
        if (fiscInfo.getIsbankaffirm() == 1) {
            // 日期一致的允许二次提交
            if (!paybankdt.substring(0, 10).equals(fiscInfo.getPaybankdt().substring(0, 10)))
                return new BaseResult(ErrorCodeEnum.BILL_PAYED);
        } else if (fiscInfo.getBillstate() == 3) {
            return new BaseResult(ErrorCodeEnum.BILL_PAYED);
        }
        try {
            //更新划解国库
            fiscInfo.setBankaffirm(bankaffirm);
            fiscInfo.setIsbankaffirm(1);
            fiscInfo.setPaybankdt(paybankdt);
            fiscInfo.setBankstation(bankstation);
            fiscInfo.setHxbankaffirm(bankaffirm);
            fiscInfo.setSendtime(sdf.format(new Date()));
            int i = fiscMapper.updateFiscBankAffirm(fiscInfo);

            if (i < 1) return new BaseResult(ErrorCodeEnum.DB_ERR.getCode(), "更新划解国库单据失败（" + billnum + "）");

            OnlineOrder oo = new OnlineOrder();
            oo.setBillnum(fiscInfo.getBillnum());
            oo.setAmt(fiscInfo.getItemmoney1().toPlainString());
            oo.setBankaffirm(fiscInfo.getBankaffirm());
            oo.setBilltype(8);
            oo.setPaybankdt(fiscInfo.getPaybankdt());
            oo.setPaychnl(paychnl);
            oo.setPayee("国库");
            oo.setPayeeaccount("");
            oo.setPayer(fiscInfo.getAccountname());
            oo.setPayeraccount(fiscInfo.getAccountcode());
            oo.setPaytype(2);
            onlineOrderService.saveOnlineOrder(oo);

            // 发送财政
            Object obj = MessageFactory.setFiscPayInfo(fiscInfo);
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            messageService.sendMessage("SETBANKPAYFISC", messageid, obj, "2.0");
            // 写凭证
            pzkService.savePzmsg("SETBANKPAYFISCPZK", pzkUtils.getFsicOne(fiscInfo));
        } catch (Exception e) {
            logger.info("划解国库失败：" + e, e);
            return new BaseResult(ErrorCodeEnum.TLQ_ERR);
        }
        return new BaseResult();
    }

    /**
     * 财政返回票据，入库
     * @param data 财政报文
     * @param billstate 票据状态
     * @param sn 消息sn
     */
    public void setPayFisc(String data, int billstate, String sn) {
        if (billstate == 1) {
            try {
                //xml解析器
                Serializer serializer = new Persister();
                //返回缴款书对象
                SetPayFisc fisc = serializer.read(SetPayFisc.class, new StringReader(data));

                PayFiscVO payFiscVO = new PayFiscVO(fisc);
                payFiscVO.setBillstate(billstate);
                payFiscVO.setIssend(2);
                fiscMapper.updateFisc(payFiscVO);
            } catch (Exception e) {
                logger.info("处理获取划解国库失败：" + e.toString(), e);
            }
        } else if (billstate > 1) {
            long messageid = Long.parseLong(sn.substring(sn.indexOf("-") + 1));
            fiscMapper.updateBillState(messageid, billstate);
        }

    }

    /** 财政返回票据，入库 v2.4 */
    public void setPayFiscNew(String data, int billstate, String sn) {
        //xml解析器
        Serializer serializer = new Persister();
        try {
            //正常
            if (billstate == 1) {
                //返回缴款书对象
                SetPayFiscNew fisc = serializer.read(SetPayFiscNew.class, new StringReader(data));
                PayFiscVO payFiscVO = new PayFiscVO(fisc);
                payFiscVO.setBillstate(billstate);
                payFiscVO.setIssend(2);
                fiscMapper.updateFisc(payFiscVO);
            } else {
                long messageid = Long.parseLong(sn.substring(sn.indexOf("-") + 1));
                fiscMapper.updateBillState(messageid, billstate);
            }
        } catch (Exception e) {
            logger.info("处理获取划解国库失败：" + e.toString(), e);
        }
    }

    /**
     * @param billnum 票据号
     * @auther dinggaofei
     * @Date 2022/12/27  11:20
     * @description 获取划解国库单据，并向财政获取划解国库单据信息
     */
    public BaseResult getPayFisc(String billnum) {
        //根据票据号从本地获取划解国库单据
        PayFiscVO pay = fiscMapper.findFiscInfo(billnum);
        //xml解析器
        Serializer serializer = new Persister();
        //xml转换器
        StringWriter sw = new StringWriter();
        try {
            BaseResult result = new BaseResult();
            //已缴费的直接返回
            if (pay != null && (pay.getBillstate()  == 3 || pay.getIsbankaffirm() == 1)) {
                pay.setBillstate(3);
                serializer.write(pay.getPayFisc(), sw);
                result.setData(sw.toString());
                return result;
            }

            //更新messageid
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            if (pay == null) {
                long payid = sequenceService.getNextSeq("FSPAYFISCSEQ");
                pay = new PayFiscVO();
                pay.setBillnum(billnum);
                pay.setMessageid(messageid);
                pay.setPayid(payid);
                fiscMapper.insertBlankFisc(pay);
            } else {
                pay.setMessageid(messageid);
                fiscMapper.updateMsgInfo(pay);
            }
            //从财政查询
            boolean suc = messageService.sendAndRecvMessage("GETPAYFISC", messageid, MessageFactory.getPayFisc(billnum), "2.4");
            if (suc) {
                pay = fiscMapper.findFiscInfo(billnum);
                PayFisc payFisc = pay.getPayFisc();
                serializer.write(payFisc, sw);
                result.setData(sw.toString());
                return result;
            }
            return new BaseResult(ErrorCodeEnum.BILL_GET_TIMEOUT);
        } catch (Exception e) {
            logger.info("失败：" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.SYS_ERR);
        }
    }

    /**
     * 划解国库单据列表
     *
     * @param payFiscVO
     * @param pagination
     * @return
     */

    public List<PayFiscVO> listPayFisc(PayFiscVO payFiscVO, Pagination pagination) {
        if (pagination.getRows() > 0) PageHelper.startPage(pagination.getPage(), pagination.getRows());
        return this.fiscMapper.listPayFisc(payFiscVO);
    }

    /**
     * 修改化解国库银行信息
     *
     * @param payFiscVO
     * @return
     */
    public BaseResult saveFisc(PayFiscVO payFiscVO) {
        int n = fiscMapper.saveFisc(payFiscVO);
        if (n < 1) {
            return new BaseResult(ErrorCodeEnum.DB_ERR);
        }
        return new BaseResult();
    }

    public PayFiscVO getFisc(Long payid) {

        return fiscMapper.getFisc(payid);
    }

    public BaseResult sendFisc(String billnum, PayFiscVO vo) {
        if (vo == null) vo = fiscMapper.findFiscBankAffirmBybill(billnum);
        if (vo.getIsbankaffirm() == 0) return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), "不允许发送未缴费单据");

        // 发送财政
        try {
            Object obj = MessageFactory.setFiscPayInfo(vo);
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            messageService.sendMessage("SETBANKPAYFISC", messageid, obj, "2.0");
            return new BaseResult();
        } catch (Exception e) {
            logger.info("发送财政失败。" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.TLQ_ERR);
        }
    }

    //发送
    public BaseResult sendFisc(String billids) {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<PayFiscVO> list = fiscMapper.findFisc(ids);
        for (PayFiscVO payFiscVO : list) {
            sendFisc(payFiscVO.getBillnum(), payFiscVO);
        }
        return new BaseResult();
    }

    //冲销
    public BaseResult cleanFisc(String billids, String usercode) {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<PayFiscVO> fiscList = fiscMapper.findFisc(ids);

        Calendar cal = Calendar.getInstance();
        String cxTime = sdf.format(cal.getTime());
        cal.add(Calendar.MINUTE, 0 - nonTaxConfig.CxTime);
        String chkTime = sdf.format(cal.getTime());

        String errinfo = "";
        for (PayFiscVO payFiscVO : fiscList) {
            if (StringUtil.isEmpty(payFiscVO.getSendtime()) || chkTime.compareTo(payFiscVO.getSendtime()) < 0) {
                setFiscPayBackOut(cxTime, usercode, payFiscVO);
                fiscMapper.backOutFisc(payFiscVO.getPayid());
            } else {
                errinfo += payFiscVO.getBillnum() + ",";
            }

        }
        if (!errinfo.equals("")) {
            errinfo += "超时冲销失败,其他单据冲销成功!";
            return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), errinfo);
        } else {
            errinfo = "冲销成功";
            return new BaseResult(ErrorCodeEnum.SUCCESS.getCode(), errinfo);
        }
    }

    private BaseResult setFiscPayBackOut(String backoutdt, String backoutname, PayFiscVO payFiscVO) {
        try {
            SetBankPayFiscBackOut out = new SetBankPayFiscBackOut();
            out.setPayid(payFiscVO.getPayid().toString());
            out.setBillnum(payFiscVO.getBillnum());
            out.setCantonid(StringUtil.toStr(payFiscVO.getCantonid()));
            out.setPayerbankid(StringUtil.toStr(payFiscVO.getPayerbankid()));
            out.getPayeedepart(payFiscVO.getPayeedepart());
            out.setPayeefisc(payFiscVO.getPayeefisc());
            out.setItemid(StringUtil.toStr(payFiscVO.getItemid1()));
            out.setMoney(payFiscVO.getItemmoney1().toPlainString());
            out.setBankaffirm(payFiscVO.getBankaffirm());
            out.setBankstation(payFiscVO.getBankstation());
            out.setBackoutname(backoutname);
            out.setPaybankdt(payFiscVO.getPaybankdt());
            out.setRemark("冲销");

            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            messageService.sendMessage("SETBANKPAYFISCBACKOUT", messageid, out, "2.0");
            // 写凭证
            pzkService.savePzmsgOut(BillStateUtil.BillType_FiscPay, payFiscVO.getBillnum(), payFiscVO.getBankaffirm());

            return new BaseResult();

        } catch (Exception e) {
            logger.info("国库冲销失败：" + e.toString(), e);

            return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
        }

    }

    //导出
    public void fiscExport(long bankid, String paybankdt, HttpServletResponse response) {
        if (bankid == 0 || StringUtil.isEmpty(paybankdt)) return;
        PayFiscVO vo = new PayFiscVO();
        vo.setPayerbankid(bankid);
        vo.setPaybankdt(paybankdt);
        List<PayFiscVO> payFiscVOS = fiscMapper.listPayFisc(vo);
        String[] headers = {"流水号", "票据号", "区划id", "区划编码", "区划名称", "缴款单位银行id", "银行名称", "账户名称", "账户", "收款单位财政机关", "预算级次", "项目id", "项目编码", "项目名称", "金额", "银行划款时间", "银行网点名称", "银行交易流水号", "单据状态", "发送时间", "银行核心交易流水号", "是否发送"};
        String[] col = {"payid", "billnum", "cantonid", "cantoncode", "cantonname", "payerbankid", "bankname", "accountname", "accountcode", "payeedepart", "payeefisc", "itemid1", "itemcode", "itemname", "itemmoney1", "paybankdt", "bankstation", "bankaffirm", "billstate", "sendtime","hxbankaffirm", "issend"};
        ExportSXSSFUtil ex = new ExportSXSSFUtil();
        SXSSFWorkbook workbook = ex.exportExcelSXSSF("国库单据列表", headers, col, payFiscVOS, null);
        response.setContentType("application/vnd.ms-excel");
        try {
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    new String(("国库单据.xls").getBytes(), "iso-8859-1"));
            OutputStream ouputStream = response.getOutputStream();
            workbook.write(ouputStream);
            ouputStream.flush();
            ouputStream.close();
        } catch (Exception e) {
            logger.info("导出失败：" + e.toString());
        }
    }
}




